package me.aartikov.alligator.commands;


import me.aartikov.alligator.util.Log;
import me.aartikov.alligator.NavigationContext;
import me.aartikov.alligator.destinations.AbilityDestination;
import me.aartikov.alligator.destinations.Destination;
import me.aartikov.alligator.destinations.DialogFragmentDestination;
import me.aartikov.alligator.destinations.FragmentDestination;
import me.aartikov.alligator.exceptions.MissingFlowFragmentNavigatorException;
import me.aartikov.alligator.exceptions.MissingFragmentNavigatorException;
import me.aartikov.alligator.exceptions.NavigationException;
import me.aartikov.alligator.exceptions.ScreenRegistrationException;
import me.aartikov.alligator.navigators.AbilityNavigator;
import me.aartikov.alligator.navigators.DialogFragmentNavigator;
import me.aartikov.alligator.navigators.FragmentNavigator;
import me.aartikov.alligator.Screen;
import me.aartikov.alligator.FlowScreen;

abstract class BaseCommand implements Command {
    private Class<? extends Screen> mScreenClass;

    BaseCommand() {
    }

    BaseCommand(Class<? extends Screen> screenClass) {
        mScreenClass = screenClass;
    }

    abstract protected boolean executeForActivity(AbilityDestination destination, AbilityNavigator activityNavigator) throws NavigationException;

    abstract protected boolean executeForFragment(FragmentDestination destination, FragmentNavigator fragmentNavigator) throws NavigationException;

    abstract protected void executeForDialogFragment(DialogFragmentDestination destination, DialogFragmentNavigator dialogFragmentNavigator) throws NavigationException;

    @Override
    final public boolean execute(NavigationContext navigationContext) throws NavigationException {
        Log.i("BaseCommand.execute([navigationContext]):37");
        if (mScreenClass == null) {
            executeForFragment(null, navigationContext.getFragmentNavigator());
            return true;
        }

        Destination destination = navigationContext.getNavigationFactory().getDestination(mScreenClass);
        if (destination == null) {
            throw new ScreenRegistrationException("Screen " + mScreenClass.getSimpleName() + " is not registered.");
        }

        if (destination instanceof AbilityDestination) {
            Log.i("BaseCommand.execute([navigationContext]):50");
            executeForActivity((AbilityDestination) destination, navigationContext.getActivityNavigator());
            return false;
        } else if (destination instanceof FragmentDestination) {
            Log.i("BaseCommand.execute([navigationContext]):54");
            if (FlowScreen.class.isAssignableFrom(mScreenClass)) {
                if (navigationContext.getFlowFragmentNavigator() == null) {
                    throw new MissingFlowFragmentNavigatorException();
                }
                return executeForFragment((FragmentDestination) destination, navigationContext.getFlowFragmentNavigator());
            } else {
                if (navigationContext.getFragmentNavigator() == null) {
                    throw new MissingFragmentNavigatorException();
                }
                return executeForFragment((FragmentDestination) destination, navigationContext.getFragmentNavigator());
            }
        } else if (destination instanceof DialogFragmentDestination) {
            executeForDialogFragment((DialogFragmentDestination) destination, navigationContext.getDialogFragmentNavigator());
            return true;
        } else {
            throw new UnsupportedOperationException("Unsupported destination type " + destination);
        }
    }
}
